package tools.chapter17;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author Kevin
 * @date 2020/4/7 23:04
 */
public class Cache<K, V> {
    final Map<K, V> m = new HashMap<>();
    final ReadWriteLock rwl = new ReentrantReadWriteLock();
    final Lock r = rwl.readLock();
    final Lock w = rwl.writeLock();

    public V get(K key) {
        V v = null;
        //读缓存
        r.lock();
        try {
            v = m.get(key);
        } finally {
            r.unlock();
        }
        //缓存中存在，返回
        if (v != null) {
            return v;
        }
        //缓存中不存在，查询数据库
        w.lock();
        try {
            //再次验证(二次校验)
            //其他线程可能已经查询过数据库
            v = m.get(key);
            if (v == null) {
                //查询数据库
                //给v赋值
                m.put(key, v);
            }
        } finally {
            w.unlock();
        }
        return v;
    }
/*
* 锁的升级。可惜 ReadWriteLock 并不支持这种升级。在上面的代码示例中，读锁还没有释放，此时获取写锁，会导致写锁永久等待，最终导致相关线程都被阻塞，永远也没有机会被唤醒。
* 虽然锁的升级是不允许的，但是锁的降级却是允许的
*/

    //锁升级的写法(会造成永久等待)
//    public V get1(K key) {
//        V v = null;
//        r.lock();
//        try {
//            v = m.get(key);
//            if (v == null) {
//                w.lock();
//                try {
//                    v = m.get(key);
//                    if (v == null) {
//                        //查询数据库
//                        //给v赋值
//                        m.put(key, v);
//                    }
//                } finally {
//                    w.unlock();
//                }
//            }
//        } finally {
//            r.unlock();
//        }
//        return v;
//    }
}
